/*     */ package com.zimbra.cs.account.auth;
/*     */ 
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException;
/*     */ import com.zimbra.cs.account.Domain;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.krb5.Krb5Login;
/*     */ import com.zimbra.cs.account.krb5.Krb5Principal;
/*     */ import com.zimbra.cs.account.ldap.LdapProv;
/*     */ import com.zimbra.cs.account.ldap.entry.LdapEntry;
/*     */ import java.io.PrintStream;
/*     */ import java.util.ArrayList;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.StringTokenizer;
/*     */ import javax.security.auth.login.LoginException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public abstract class AuthMechanism
/*     */ {
/*     */   protected AuthMech authMech;
/*     */   
/*     */   public static enum AuthMech
/*     */   {
/*  45 */     zimbra, 
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  51 */     ldap, 
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  57 */     ad, 
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  67 */     kerberos5, 
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  74 */     custom;
/*     */     
/*     */     private AuthMech() {}
/*  77 */     public static AuthMech fromString(String authMechStr) throws ServiceException { if (authMechStr == null) {
/*  78 */         return null;
/*     */       }
/*     */       try
/*     */       {
/*  82 */         return valueOf(authMechStr);
/*     */       } catch (IllegalArgumentException e) {
/*  84 */         throw ServiceException.INVALID_REQUEST("unknown auth mech: " + authMechStr, e);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   protected AuthMechanism(AuthMech authMech)
/*     */   {
/*  92 */     this.authMech = authMech;
/*     */   }
/*     */   
/*     */   public static AuthMechanism newInstance(Account acct, Map<String, Object> context) throws ServiceException
/*     */   {
/*  97 */     String authMechStr = AuthMech.zimbra.name();
/*     */     
/*     */ 
/*     */ 
/* 101 */     if (!acct.isIsExternalVirtualAccount()) {
/* 102 */       Provisioning prov = Provisioning.getInstance();
/* 103 */       Domain domain = prov.getDomain(acct);
/*     */       
/*     */ 
/* 106 */       if (domain != null)
/*     */       {
/* 108 */         Boolean asAdmin = context == null ? null : (Boolean)context.get("asAdmin");
/* 109 */         String am; if ((asAdmin != null) && (asAdmin.booleanValue())) {
/* 110 */           String am = domain.getAuthMechAdmin();
/* 111 */           if (am == null)
/*     */           {
/* 113 */             am = domain.getAuthMech();
/*     */           }
/*     */         } else {
/* 116 */           am = domain.getAuthMech();
/*     */         }
/*     */         
/* 119 */         if (am != null) {
/* 120 */           authMechStr = am;
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 126 */     if (authMechStr.startsWith(AuthMech.custom.name() + ":")) {
/* 127 */       return new CustomAuth(AuthMech.custom, authMechStr);
/*     */     }
/*     */     try {
/* 130 */       AuthMech authMech = AuthMech.fromString(authMechStr);
/*     */       
/* 132 */       switch (authMech) {
/*     */       case zimbra: 
/* 134 */         return new ZimbraAuth(authMech);
/*     */       case ldap: 
/*     */       case ad: 
/* 137 */         return new LdapAuth(authMech);
/*     */       case kerberos5: 
/* 139 */         return new Kerberos5Auth(authMech);
/*     */       }
/*     */     } catch (ServiceException e) {
/* 142 */       ZimbraLog.account.warn("invalid auth mech", e);
/*     */     }
/*     */     
/* 145 */     ZimbraLog.account.warn("unknown value for zimbraAuthMech: " + authMechStr + ", falling back to default mech");
/*     */     
/* 147 */     return new ZimbraAuth(AuthMech.zimbra);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public static void doZimbraAuth(LdapProv prov, Domain domain, Account acct, String password, Map<String, Object> authCtxt)
/*     */     throws ServiceException
/*     */   {
/* 155 */     ZimbraAuth zimbraAuth = new ZimbraAuth(AuthMech.zimbra);
/* 156 */     zimbraAuth.doAuth(prov, domain, acct, password, authCtxt);
/*     */   }
/*     */   
/*     */   public boolean isZimbraAuth() {
/* 160 */     return false;
/*     */   }
/*     */   
/*     */   public abstract boolean checkPasswordAging()
/*     */     throws ServiceException;
/*     */   
/*     */   public abstract void doAuth(LdapProv paramLdapProv, Domain paramDomain, Account paramAccount, String paramString, Map<String, Object> paramMap) throws ServiceException;
/*     */   
/*     */   public AuthMech getMechanism()
/*     */   {
/* 170 */     return this.authMech;
/*     */   }
/*     */   
/*     */   public static String namePassedIn(Map<String, Object> authCtxt) {
/*     */     String npi;
/* 175 */     if (authCtxt != null) {
/* 176 */       String npi = (String)authCtxt.get("anp");
/* 177 */       if (npi == null)
/* 178 */         npi = "";
/*     */     } else {
/* 180 */       npi = ""; }
/* 181 */     return npi;
/*     */   }
/*     */   
/*     */   public static class ZimbraAuth
/*     */     extends AuthMechanism
/*     */   {
/*     */     ZimbraAuth(AuthMechanism.AuthMech authMech)
/*     */     {
/* 189 */       super();
/*     */     }
/*     */     
/*     */     public boolean isZimbraAuth()
/*     */     {
/* 194 */       return true;
/*     */     }
/*     */     
/*     */ 
/*     */     public void doAuth(LdapProv prov, Domain domain, Account acct, String password, Map<String, Object> authCtxt)
/*     */       throws ServiceException
/*     */     {
/* 201 */       String encodedPassword = acct.getAttr("userPassword");
/*     */       
/* 203 */       if (encodedPassword == null) {
/* 204 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt), "missing userPassword");
/*     */       }
/*     */       
/*     */ 
/* 208 */       if (PasswordUtil.SSHA512.isSSHA512(encodedPassword)) {
/* 209 */         if (PasswordUtil.SSHA512.verifySSHA512(encodedPassword, password)) {
/* 210 */           return;
/*     */         }
/* 212 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt), "invalid password");
/*     */       }
/*     */       
/* 215 */       if (PasswordUtil.SSHA.isSSHA(encodedPassword)) {
/* 216 */         if (PasswordUtil.SSHA.verifySSHA(encodedPassword, password)) {
/* 217 */           return;
/*     */         }
/* 219 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt), "invalid password");
/*     */       }
/*     */       
/* 222 */       if ((acct instanceof LdapEntry))
/*     */       {
/* 224 */         prov.zimbraLdapAuthenticate(acct, password, authCtxt);
/* 225 */         return;
/*     */       }
/* 227 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt));
/*     */     }
/*     */     
/*     */     public boolean checkPasswordAging() throws ServiceException
/*     */     {
/* 232 */       return true;
/*     */     }
/*     */   }
/*     */   
/*     */   static class LdapAuth
/*     */     extends AuthMechanism
/*     */   {
/*     */     LdapAuth(AuthMechanism.AuthMech authMech)
/*     */     {
/* 241 */       super();
/*     */     }
/*     */     
/*     */     public void doAuth(LdapProv prov, Domain domain, Account acct, String password, Map<String, Object> authCtxt)
/*     */       throws ServiceException
/*     */     {
/* 247 */       prov.externalLdapAuth(domain, this.authMech, acct, password, authCtxt);
/*     */     }
/*     */     
/*     */     public boolean checkPasswordAging() throws ServiceException
/*     */     {
/* 252 */       return false;
/*     */     }
/*     */   }
/*     */   
/*     */   static class Kerberos5Auth
/*     */     extends AuthMechanism
/*     */   {
/*     */     Kerberos5Auth(AuthMechanism.AuthMech authMech)
/*     */     {
/* 261 */       super();
/*     */     }
/*     */     
/*     */     public void doAuth(LdapProv prov, Domain domain, Account acct, String password, Map<String, Object> authCtxt)
/*     */       throws ServiceException
/*     */     {
/* 267 */       String principal = Krb5Principal.getKrb5Principal(domain, acct);
/*     */       
/* 269 */       if (principal == null) {
/* 270 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt), "cannot obtain principal for " + this.authMech.name() + " auth");
/*     */       }
/*     */       
/* 273 */       if (principal != null) {
/*     */         try {
/* 275 */           Krb5Login.verifyPassword(principal, password);
/*     */         } catch (LoginException e) {
/* 277 */           throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt) + "(kerberos5 principal: " + principal + ")", e.getMessage(), e);
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */     public boolean checkPasswordAging()
/*     */       throws ServiceException
/*     */     {
/* 285 */       return false;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   static class CustomAuth
/*     */     extends AuthMechanism
/*     */   {
/*     */     private String authMechStr;
/*     */     
/* 295 */     private String mHandlerName = "";
/*     */     private ZimbraCustomAuth mHandler;
/*     */     List<String> mArgs;
/*     */     
/*     */     CustomAuth(AuthMechanism.AuthMech authMech, String authMechStr) {
/* 300 */       super();
/* 301 */       this.authMechStr = authMechStr;
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 317 */       int handlerNameStart = authMechStr.indexOf(':');
/* 318 */       if (handlerNameStart != -1) {
/* 319 */         int handlerNameEnd = authMechStr.indexOf(' ');
/* 320 */         if (handlerNameEnd != -1) {
/* 321 */           this.mHandlerName = authMechStr.substring(handlerNameStart + 1, handlerNameEnd);
/* 322 */           AuthMechanism.QuotedStringParser parser = new AuthMechanism.QuotedStringParser(authMechStr.substring(handlerNameEnd + 1));
/* 323 */           this.mArgs = parser.parse();
/* 324 */           if (this.mArgs.size() == 0)
/* 325 */             this.mArgs = null;
/*     */         } else {
/* 327 */           this.mHandlerName = authMechStr.substring(handlerNameStart + 1);
/*     */         }
/*     */         
/* 330 */         if (!StringUtil.isNullOrEmpty(this.mHandlerName)) {
/* 331 */           this.mHandler = ZimbraCustomAuth.getHandler(this.mHandlerName);
/*     */         }
/*     */       }
/* 334 */       if (ZimbraLog.account.isDebugEnabled()) {
/* 335 */         StringBuffer sb = null;
/* 336 */         if (this.mArgs != null) {
/* 337 */           sb = new StringBuffer();
/* 338 */           for (String s : this.mArgs)
/* 339 */             sb.append("[" + s + "] ");
/*     */         }
/* 341 */         ZimbraLog.account.debug("CustomAuth: handlerName=" + this.mHandlerName + ", args=" + sb);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */     public void doAuth(LdapProv prov, Domain domain, Account acct, String password, Map<String, Object> authCtxt)
/*     */       throws ServiceException
/*     */     {
/* 349 */       if (this.mHandler == null) {
/* 350 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt), "handler " + this.mHandlerName + " for custom auth for domain " + domain.getName() + " not found");
/*     */       }
/*     */       
/*     */       try
/*     */       {
/* 355 */         this.mHandler.authenticate(acct, password, authCtxt, this.mArgs);
/* 356 */         return;
/*     */       } catch (Exception e) {
/* 358 */         if ((e instanceof ServiceException)) {
/* 359 */           throw ((ServiceException)e);
/*     */         }
/* 361 */         String msg = e.getMessage();
/* 362 */         if (StringUtil.isNullOrEmpty(msg)) {
/* 363 */           msg = "";
/*     */         } else {
/* 365 */           msg = " (" + msg + ")";
/*     */         }
/*     */         
/*     */ 
/*     */ 
/* 370 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt) + msg, msg, e);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */     public boolean checkPasswordAging()
/*     */       throws ServiceException
/*     */     {
/* 378 */       if (this.mHandler == null)
/* 379 */         throw ServiceException.FAILURE("custom auth handler " + this.mHandlerName + " not found", null);
/* 380 */       return this.mHandler.checkPasswordAging();
/*     */     }
/*     */   }
/*     */   
/*     */   static class QuotedStringParser
/*     */   {
/*     */     private String mInput;
/*     */     private static final String DELIM_WHITESPACE_AND_QUOTES = " \t\r\n\"";
/*     */     private static final String DELIM_QUOTES_ONLY = "\"";
/*     */     
/*     */     public QuotedStringParser(String input)
/*     */     {
/* 392 */       if (input == null)
/* 393 */         throw new IllegalArgumentException("Search Text cannot be null.");
/* 394 */       this.mInput = input;
/*     */     }
/*     */     
/*     */     public List<String> parse() {
/* 398 */       List<String> result = new ArrayList();
/*     */       
/* 400 */       boolean returnTokens = true;
/* 401 */       String currentDelims = " \t\r\n\"";
/* 402 */       StringTokenizer parser = new StringTokenizer(this.mInput, currentDelims, returnTokens);
/*     */       
/* 404 */       boolean openDoubleQuote = false;
/* 405 */       boolean gotContent = false;
/* 406 */       String token = null;
/* 407 */       while (parser.hasMoreTokens()) {
/* 408 */         token = parser.nextToken(currentDelims);
/* 409 */         if (!isDoubleQuote(token)) {
/* 410 */           if (!currentDelims.contains(token)) {
/* 411 */             result.add(token);
/* 412 */             gotContent = true;
/*     */           }
/*     */         } else {
/* 415 */           currentDelims = flipDelimiters(currentDelims);
/*     */           
/* 417 */           if ((openDoubleQuote) && (!gotContent))
/* 418 */             result.add("");
/* 419 */           openDoubleQuote = !openDoubleQuote;
/* 420 */           gotContent = false;
/*     */         }
/*     */       }
/* 423 */       return result;
/*     */     }
/*     */     
/*     */     private boolean isDoubleQuote(String token) {
/* 427 */       return token.equals("\"");
/*     */     }
/*     */     
/*     */     private String flipDelimiters(String curDelims) {
/* 431 */       if (curDelims.equals(" \t\r\n\"")) {
/* 432 */         return "\"";
/*     */       }
/* 434 */       return " \t\r\n\"";
/*     */     }
/*     */   }
/*     */   
/*     */   public static void main(String[] args) {
/* 439 */     QuotedStringParser parser = new QuotedStringParser("http://blah.com:123    green \" ocean blue   \"  \"\" yelllow \"\"");
/* 440 */     List<String> tokens = parser.parse();
/* 441 */     int i = 0;
/* 442 */     for (String s : tokens) {
/* 443 */       System.out.format("%d [%s]\n", new Object[] { Integer.valueOf(++i), s });
/*     */     }
/* 445 */     CustomAuth ca = new CustomAuth(AuthMech.custom, "custom:sample http://blah.com:123    green \" ocean blue   \"  \"\" yelllow \"\"");
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/account/auth/AuthMechanism.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */